]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
st/scroll-view: Stop implementing ClutterContainer
authorZander Brown <zbrown@gnome.org>
Wed, 8 Nov 2023 07:36:30 +0000 (07:36 +0000)
committerMarge Bot <marge-bot@gnome.org>
Fri, 10 Nov 2023 20:19:13 +0000 (20:19 +0000)
Instead, listen to ::actor-{added,removed} allowing ClutterActor's
regular add/remove API to work as expected — at least so long only one
child is added

We also no longer inherit StBin as we actually have up to three
children (including the two scrollbars), but by implementing :child
ourselves the API seen by JS is unchanged

Fix: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2661
Fix: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3172
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3010>

src/st/st-scroll-view.c
src/st/st-scroll-view.h

index c8c776128da78d763b58475914458e5e9e393466..1576f6e44cd8dbfc3b65df6e672aec8197a53074 100644 (file)
 #include <clutter/clutter.h>
 #include <math.h>
 
-static void clutter_container_iface_init (ClutterContainerIface *iface);
-
-static ClutterContainerIface *st_scroll_view_parent_iface = NULL;
-
+typedef struct _StScrollViewPrivate  StScrollViewPrivate;
 struct _StScrollViewPrivate
 {
-  /* a pointer to the child; this is actually stored
-   * inside StBin:child, but we keep it to avoid
-   * calling st_bin_get_child() every time we need it
-   */
   ClutterActor *child;
 
   StAdjustment *hadjustment;
@@ -98,14 +91,12 @@ struct _StScrollViewPrivate
   guint         vscrollbar_visible : 1;
 };
 
-G_DEFINE_TYPE_WITH_CODE (StScrollView, st_scroll_view, ST_TYPE_BIN,
-                         G_ADD_PRIVATE (StScrollView)
-                         G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
-                                                clutter_container_iface_init))
+G_DEFINE_TYPE_WITH_PRIVATE (StScrollView, st_scroll_view, ST_TYPE_WIDGET)
 
 enum {
   PROP_0,
 
+  PROP_CHILD,
   PROP_HSCROLL,
   PROP_VSCROLL,
   PROP_HSCROLLBAR_POLICY,
@@ -126,10 +117,14 @@ st_scroll_view_get_property (GObject    *object,
                              GValue     *value,
                              GParamSpec *pspec)
 {
-  StScrollViewPrivate *priv = ((StScrollView *) object)->priv;
+  StScrollViewPrivate *priv =
+    st_scroll_view_get_instance_private (ST_SCROLL_VIEW (object));
 
   switch (property_id)
     {
+    case PROP_CHILD:
+      g_value_set_object (value, priv->child);
+      break;
     case PROP_HSCROLL:
       g_value_set_object (value, priv->hscroll);
       break;
@@ -210,10 +205,13 @@ st_scroll_view_set_property (GObject      *object,
                              GParamSpec   *pspec)
 {
   StScrollView *self = ST_SCROLL_VIEW (object);
-  StScrollViewPrivate *priv = self->priv;
+  StScrollViewPrivate *priv = st_scroll_view_get_instance_private (self);
 
   switch (property_id)
     {
+    case PROP_CHILD:
+      st_scroll_view_set_child (self, g_value_get_object (value));
+      break;
     case PROP_MOUSE_SCROLL:
       st_scroll_view_set_mouse_scrolling (self,
                                           g_value_get_boolean (value));
@@ -240,15 +238,17 @@ st_scroll_view_set_property (GObject      *object,
 static void
 st_scroll_view_dispose (GObject *object)
 {
-  StScrollViewPrivate *priv = ST_SCROLL_VIEW (object)->priv;
+  StScrollViewPrivate *priv =
+    st_scroll_view_get_instance_private (ST_SCROLL_VIEW (object));
 
   /* The fade effect disconnects from the adjustments and
    * needs to be removed while those are still alive.
    */
   clutter_actor_clear_effects (CLUTTER_ACTOR (object));
 
-  g_clear_pointer (&priv->vscroll, clutter_actor_destroy);
-  g_clear_pointer (&priv->hscroll, clutter_actor_destroy);
+  g_clear_weak_pointer (&priv->child);
+  g_clear_weak_pointer (&priv->vscroll);
+  g_clear_weak_pointer (&priv->hscroll);
 
   /* For most reliable freeing of memory, an object with signals
    * like StAdjustment should be explicitly disposed. Since we own
@@ -256,18 +256,14 @@ st_scroll_view_dispose (GObject *object)
    * the signal handlers that we established on creation.
    */
   if (priv->hadjustment)
-    {
-      g_object_run_dispose (G_OBJECT (priv->hadjustment));
-      g_object_unref (priv->hadjustment);
-      priv->hadjustment = NULL;
-    }
+    g_object_run_dispose (G_OBJECT (priv->hadjustment));
+
+  g_clear_object (&priv->hadjustment);
 
   if (priv->vadjustment)
-    {
-      g_object_run_dispose (G_OBJECT (priv->vadjustment));
-      g_object_unref (priv->vadjustment);
-      priv->vadjustment = NULL;
-    }
+    g_object_run_dispose (G_OBJECT (priv->vadjustment));
+
+  g_clear_object (&priv->vadjustment);
 
   G_OBJECT_CLASS (st_scroll_view_parent_class)->dispose (object);
 }
@@ -276,7 +272,8 @@ static void
 st_scroll_view_paint (ClutterActor        *actor,
                       ClutterPaintContext *paint_context)
 {
-  StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv;
+  StScrollViewPrivate *priv =
+    st_scroll_view_get_instance_private (ST_SCROLL_VIEW (actor));
 
   st_widget_paint_background (ST_WIDGET (actor), paint_context);
 
@@ -292,7 +289,8 @@ static void
 st_scroll_view_pick (ClutterActor       *actor,
                      ClutterPickContext *pick_context)
 {
-  StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv;
+  StScrollViewPrivate *priv =
+    st_scroll_view_get_instance_private (ST_SCROLL_VIEW (actor));
 
   /* Chain up so we get a bounding box pained (if we are reactive) */
   CLUTTER_ACTOR_CLASS (st_scroll_view_parent_class)->pick (actor, pick_context);
@@ -316,7 +314,7 @@ static double
 get_scrollbar_width (StScrollView *scroll,
                      gfloat        for_height)
 {
-  StScrollViewPrivate *priv = scroll->priv;
+  StScrollViewPrivate *priv = st_scroll_view_get_instance_private (scroll);
 
   if (clutter_actor_is_visible (priv->vscroll))
     {
@@ -334,7 +332,7 @@ static double
 get_scrollbar_height (StScrollView *scroll,
                       gfloat        for_width)
 {
-  StScrollViewPrivate *priv = scroll->priv;
+  StScrollViewPrivate *priv = st_scroll_view_get_instance_private (scroll);
 
   if (clutter_actor_is_visible (priv->hscroll))
     {
@@ -355,7 +353,8 @@ st_scroll_view_get_preferred_width (ClutterActor *actor,
                                     gfloat       *min_width_p,
                                     gfloat       *natural_width_p)
 {
-  StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv;
+  StScrollViewPrivate *priv =
+    st_scroll_view_get_instance_private (ST_SCROLL_VIEW (actor));
   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
   gboolean account_for_vscrollbar = FALSE;
   gfloat min_width = 0, natural_width;
@@ -432,7 +431,8 @@ st_scroll_view_get_preferred_height (ClutterActor *actor,
                                      gfloat       *min_height_p,
                                      gfloat       *natural_height_p)
 {
-  StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv;
+  StScrollViewPrivate *priv =
+    st_scroll_view_get_instance_private (ST_SCROLL_VIEW (actor));
   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
   gboolean account_for_hscrollbar = FALSE;
   gfloat min_height = 0, natural_height;
@@ -532,11 +532,11 @@ static void
 st_scroll_view_allocate (ClutterActor          *actor,
                          const ClutterActorBox *box)
 {
+  StScrollViewPrivate *priv =
+    st_scroll_view_get_instance_private (ST_SCROLL_VIEW (actor));
   ClutterActorBox content_box, child_box;
   gfloat avail_width, avail_height, sb_width, sb_height;
   gboolean hscrollbar_visible, vscrollbar_visible;
-
-  StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv;
   StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
 
   clutter_actor_set_allocation (actor, box);
@@ -762,7 +762,8 @@ static gboolean
 st_scroll_view_scroll_event (ClutterActor *self,
                              ClutterEvent *event)
 {
-  StScrollViewPrivate *priv = ST_SCROLL_VIEW (self)->priv;
+  StScrollViewPrivate *priv =
+    st_scroll_view_get_instance_private (ST_SCROLL_VIEW (self));
   ClutterTextDirection direction;
   ClutterScrollDirection scroll_direction;
 
@@ -818,6 +819,44 @@ st_scroll_view_scroll_event (ClutterActor *self,
   return TRUE;
 }
 
+static void
+st_scroll_view_popup_menu (StWidget *widget)
+{
+  StScrollViewPrivate *priv =
+    st_scroll_view_get_instance_private (ST_SCROLL_VIEW (widget));
+
+  if (priv->child && ST_IS_WIDGET (priv->child))
+    st_widget_popup_menu (ST_WIDGET (priv->child));
+}
+
+static gboolean
+st_scroll_view_navigate_focus (StWidget         *widget,
+                               ClutterActor     *from,
+                               StDirectionType   direction)
+{
+  StScrollViewPrivate *priv =
+    st_scroll_view_get_instance_private (ST_SCROLL_VIEW (widget));
+  ClutterActor *bin_actor = CLUTTER_ACTOR (widget);
+
+  if (st_widget_get_can_focus (widget))
+    {
+      if (from && clutter_actor_contains (bin_actor, from))
+        return FALSE;
+
+      if (clutter_actor_is_mapped (bin_actor))
+        {
+          clutter_actor_grab_key_focus (bin_actor);
+          return TRUE;
+        }
+      else
+        return FALSE;
+    }
+  else if (priv->child && ST_IS_WIDGET (priv->child))
+    return st_widget_navigate_focus (ST_WIDGET (priv->child), from, direction, FALSE);
+  else
+    return FALSE;
+}
+
 static void
 st_scroll_view_class_init (StScrollViewClass *klass)
 {
@@ -838,6 +877,18 @@ st_scroll_view_class_init (StScrollViewClass *klass)
   actor_class->scroll_event = st_scroll_view_scroll_event;
 
   widget_class->style_changed = st_scroll_view_style_changed;
+  widget_class->popup_menu = st_scroll_view_popup_menu;
+  widget_class->navigate_focus = st_scroll_view_navigate_focus;
+
+  /**
+   * StScrollView:child:
+   *
+   * The child #StScrollable of the #StScrollView container.
+   */
+  props[PROP_CHILD] =
+    g_param_spec_object ("child", NULL, NULL,
+                         ST_TYPE_SCROLLABLE,
+                         ST_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
 
   /**
    * StScrollView:hscroll:
@@ -941,107 +992,99 @@ st_scroll_view_class_init (StScrollViewClass *klass)
 }
 
 static void
-st_scroll_view_init (StScrollView *self)
+set_child (StScrollView *scroll, ClutterActor *child)
 {
-  StScrollViewPrivate *priv = self->priv = st_scroll_view_get_instance_private (self);
+  StScrollViewPrivate *priv = st_scroll_view_get_instance_private (scroll);
+  ClutterActor *old = priv->child;
 
-  priv->hscrollbar_policy = ST_POLICY_AUTOMATIC;
-  priv->vscrollbar_policy = ST_POLICY_AUTOMATIC;
+  if (!g_set_weak_pointer (&priv->child, child))
+    return;
 
-  priv->hadjustment = g_object_new (ST_TYPE_ADJUSTMENT,
-                                    "actor", self,
-                                    NULL);
-  priv->hscroll = g_object_new (ST_TYPE_SCROLL_BAR,
-                                "adjustment", priv->hadjustment,
-                                "vertical", FALSE,
-                                NULL);
+  if (old)
+    st_scrollable_set_adjustments (ST_SCROLLABLE (old), NULL, NULL);
 
-  priv->vadjustment = g_object_new (ST_TYPE_ADJUSTMENT,
-                                    "actor", self,
-                                    NULL);
-  priv->vscroll = g_object_new (ST_TYPE_SCROLL_BAR,
-                                "adjustment", priv->vadjustment,
-                                "vertical", TRUE,
-                                NULL);
-
-  clutter_actor_add_child (CLUTTER_ACTOR (self), priv->hscroll);
-  clutter_actor_add_child (CLUTTER_ACTOR (self), priv->vscroll);
+  if (priv->child)
+    st_scrollable_set_adjustments (ST_SCROLLABLE (priv->child),
+                                   priv->hadjustment,
+                                   priv->vadjustment);
 
-  /* mouse scroll is enabled by default, so we also need to be reactive */
-  priv->mouse_scroll = TRUE;
-  g_object_set (G_OBJECT (self), "reactive", TRUE, NULL);
+  g_object_notify_by_pspec (G_OBJECT (scroll), props[PROP_CHILD]);
 }
 
 static void
-st_scroll_view_add (ClutterContainer *container,
-                    ClutterActor     *actor)
+actor_added (ClutterActor *container,
+             ClutterActor *actor)
 {
-  StScrollView *self = ST_SCROLL_VIEW (container);
-  StScrollViewPrivate *priv = self->priv;
-
-  if (ST_IS_SCROLLABLE (actor))
-    {
-      priv->child = actor;
-
-      /* chain up to StBin::add() */
-      st_scroll_view_parent_iface->add (container, actor);
+  StScrollView *scroll = ST_SCROLL_VIEW (container);
+  StScrollViewPrivate *priv = st_scroll_view_get_instance_private (scroll);
 
-      st_scrollable_set_adjustments (ST_SCROLLABLE (actor),
-                                     priv->hadjustment, priv->vadjustment);
-    }
-  else
+  if (!ST_IS_SCROLLABLE (actor))
     {
       g_warning ("Attempting to add an actor of type %s to "
-                 "a StScrollView, but the actor does "
+                 "an StScrollView, but the actor does "
                  "not implement StScrollable.",
-                 g_type_name (G_OBJECT_TYPE (actor)));
+                 G_OBJECT_TYPE_NAME (actor));
+      return;
     }
+
+  if (priv->child)
+    g_warning ("Attempting to add an actor of type %s to "
+               "an StScrollView, but the view already contains a %s. "
+               "Was add_child() used repeatedly?",
+               G_OBJECT_TYPE_NAME (actor),
+               G_OBJECT_TYPE_NAME (priv->child));
+
+  set_child (scroll, actor);
 }
 
 static void
-st_scroll_view_remove (ClutterContainer *container,
-                       ClutterActor     *actor)
+actor_removed (ClutterActor *container,
+               ClutterActor *actor)
 {
-  StScrollView *self = ST_SCROLL_VIEW (container);
-  StScrollViewPrivate *priv = self->priv;
+  StScrollView *scroll = ST_SCROLL_VIEW (container);
+  StScrollViewPrivate *priv = st_scroll_view_get_instance_private (scroll);
 
-  if (actor == priv->child)
-    {
-      g_object_ref (priv->child);
+  if (priv->child == actor)
+    set_child (scroll, NULL);
+}
 
-      /* chain up to StBin::remove() */
-      st_scroll_view_parent_iface->remove (container, actor);
+static void
+st_scroll_view_init (StScrollView *self)
+{
+  StScrollViewPrivate *priv = st_scroll_view_get_instance_private (self);
+  ClutterActor *scrollbar;
 
-      st_scrollable_set_adjustments (ST_SCROLLABLE (priv->child),
-                                     NULL, NULL);
+  priv->hscrollbar_policy = ST_POLICY_AUTOMATIC;
+  priv->vscrollbar_policy = ST_POLICY_AUTOMATIC;
 
-      g_object_unref (priv->child);
-      priv->child = NULL;
-    }
-  else
-    {
-      if (actor == priv->vscroll)
-        priv->vscroll = NULL;
-      else if (actor == priv->hscroll)
-        priv->hscroll = NULL;
-      else
-        g_assert ("Unknown child removed from StScrollView");
+  priv->hadjustment = g_object_new (ST_TYPE_ADJUSTMENT,
+                                    "actor", self,
+                                    NULL);
+  scrollbar = g_object_new (ST_TYPE_SCROLL_BAR,
+                            "adjustment", priv->hadjustment,
+                            "vertical", FALSE,
+                            NULL);
+  g_set_weak_pointer (&priv->hscroll, scrollbar);
 
-      clutter_actor_remove_child (CLUTTER_ACTOR (container), actor);
-    }
-}
+  priv->vadjustment = g_object_new (ST_TYPE_ADJUSTMENT,
+                                    "actor", self,
+                                    NULL);
+  scrollbar = g_object_new (ST_TYPE_SCROLL_BAR,
+                            "adjustment", priv->vadjustment,
+                            "vertical", TRUE,
+                            NULL);
+  g_set_weak_pointer (&priv->vscroll, scrollbar);
 
-static void
-clutter_container_iface_init (ClutterContainerIface *iface)
-{
-  /* store a pointer to the StBin implementation of
-   * ClutterContainer so that we can chain up when
-   * overriding the methods
-   */
-  st_scroll_view_parent_iface = g_type_interface_peek_parent (iface);
+  clutter_actor_add_child (CLUTTER_ACTOR (self), priv->hscroll);
+  clutter_actor_add_child (CLUTTER_ACTOR (self), priv->vscroll);
+
+  /* mouse scroll is enabled by default, so we also need to be reactive */
+  priv->mouse_scroll = TRUE;
+  clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
 
-  iface->add = st_scroll_view_add;
-  iface->remove = st_scroll_view_remove;
+  /* Connect these *after* we've added our internal actors */
+  g_signal_connect (self, "actor-added", G_CALLBACK (actor_added), NULL);
+  g_signal_connect (self, "actor-removed", G_CALLBACK (actor_removed), NULL);
 }
 
 /**
@@ -1057,6 +1100,61 @@ st_scroll_view_new (void)
   return g_object_new (ST_TYPE_SCROLL_VIEW, NULL);
 }
 
+/**
+ * st_scroll_view_get_child:
+ * @scroll: a #StBin
+ *
+ * Gets the #StScrollable content of @scroll.
+ *
+ * Returns: (transfer none) (nullable): a #StScrollable, or %NULL
+ */
+StScrollable *
+st_scroll_view_get_child (StScrollView *scroll)
+{
+  StScrollViewPrivate *priv;
+
+  g_return_val_if_fail (ST_IS_SCROLL_VIEW (scroll), NULL);
+
+  priv = st_scroll_view_get_instance_private (scroll);
+
+  if (!priv->child)
+    return NULL;
+
+  return ST_SCROLLABLE (priv->child);
+}
+
+/**
+ * st_scroll_view_set_child:
+ * @scroll: a #StScrollView
+ * @child: (nullable): a #StScrollable, or %NULL
+ *
+ * Sets @child as the content of @scroll.
+ *
+ * If @scroll already has a child, the previous child is removed.
+ */
+void
+st_scroll_view_set_child (StScrollView *scroll,
+                          StScrollable *child)
+{
+  StScrollViewPrivate *priv;
+
+  g_return_if_fail (ST_IS_SCROLL_VIEW (scroll));
+  g_return_if_fail (child == NULL || ST_IS_SCROLLABLE (child));
+
+  priv = st_scroll_view_get_instance_private (scroll);
+
+  g_object_freeze_notify (G_OBJECT (scroll));
+
+  if (priv->child)
+    clutter_actor_remove_child (CLUTTER_ACTOR (scroll), priv->child);
+
+  if (child)
+    clutter_actor_add_child (CLUTTER_ACTOR (scroll),
+                             CLUTTER_ACTOR (child));
+
+  g_object_thaw_notify (G_OBJECT (scroll));
+}
+
 /**
  * st_scroll_view_get_hscroll_bar:
  * @scroll: a #StScrollView
@@ -1068,9 +1166,13 @@ st_scroll_view_new (void)
 ClutterActor *
 st_scroll_view_get_hscroll_bar (StScrollView *scroll)
 {
+  StScrollViewPrivate *priv;
+
   g_return_val_if_fail (ST_IS_SCROLL_VIEW (scroll), NULL);
 
-  return scroll->priv->hscroll;
+  priv = st_scroll_view_get_instance_private (scroll);
+
+  return priv->hscroll;
 }
 
 /**
@@ -1084,9 +1186,13 @@ st_scroll_view_get_hscroll_bar (StScrollView *scroll)
 ClutterActor *
 st_scroll_view_get_vscroll_bar (StScrollView *scroll)
 {
+  StScrollViewPrivate *priv;
+
   g_return_val_if_fail (ST_IS_SCROLL_VIEW (scroll), NULL);
 
-  return scroll->priv->vscroll;
+  priv = st_scroll_view_get_instance_private (scroll);
+
+  return priv->vscroll;
 }
 
 /**
@@ -1100,11 +1206,14 @@ st_scroll_view_get_vscroll_bar (StScrollView *scroll)
 gfloat
 st_scroll_view_get_column_size (StScrollView *scroll)
 {
+  StScrollViewPrivate *priv;
   gdouble column_size;
 
-  g_return_val_if_fail (scroll, 0);
+  g_return_val_if_fail (ST_IS_SCROLL_VIEW (scroll), 0);
+
+  priv = st_scroll_view_get_instance_private (scroll);
 
-  g_object_get (scroll->priv->hadjustment,
+  g_object_get (priv->hadjustment,
                 "step-increment", &column_size,
                 NULL);
 
@@ -1122,20 +1231,24 @@ void
 st_scroll_view_set_column_size (StScrollView *scroll,
                                 gfloat        column_size)
 {
-  g_return_if_fail (scroll);
+  StScrollViewPrivate *priv;
+
+  g_return_if_fail (ST_IS_SCROLL_VIEW (scroll));
+
+  priv = st_scroll_view_get_instance_private (scroll);
 
   if (column_size < 0)
     {
-      scroll->priv->column_size_set = FALSE;
-      scroll->priv->column_size = -1;
+      priv->column_size_set = FALSE;
+      priv->column_size = -1;
     }
   else
     {
-      scroll->priv->column_size_set = TRUE;
-      scroll->priv->column_size = column_size;
+      priv->column_size_set = TRUE;
+      priv->column_size = column_size;
 
-      g_object_set (scroll->priv->hadjustment,
-                    "step-increment", (gdouble) scroll->priv->column_size,
+      g_object_set (priv->hadjustment,
+                    "step-increment", (double) priv->column_size,
                     NULL);
     }
 }
@@ -1151,11 +1264,14 @@ st_scroll_view_set_column_size (StScrollView *scroll,
 gfloat
 st_scroll_view_get_row_size (StScrollView *scroll)
 {
+  StScrollViewPrivate *priv;
   gdouble row_size;
 
-  g_return_val_if_fail (scroll, 0);
+  g_return_val_if_fail (ST_IS_SCROLL_VIEW (scroll), 0);
+
+  priv = st_scroll_view_get_instance_private (scroll);
 
-  g_object_get (scroll->priv->vadjustment,
+  g_object_get (priv->vadjustment,
                 "step-increment", &row_size,
                 NULL);
 
@@ -1173,20 +1289,24 @@ void
 st_scroll_view_set_row_size (StScrollView *scroll,
                              gfloat        row_size)
 {
-  g_return_if_fail (scroll);
+  StScrollViewPrivate *priv;
+
+  g_return_if_fail (ST_IS_SCROLL_VIEW (scroll));
+
+  priv = st_scroll_view_get_instance_private (scroll);
 
   if (row_size < 0)
     {
-      scroll->priv->row_size_set = FALSE;
-      scroll->priv->row_size = -1;
+      priv->row_size_set = FALSE;
+      priv->row_size = -1;
     }
   else
     {
-      scroll->priv->row_size_set = TRUE;
-      scroll->priv->row_size = row_size;
+      priv->row_size_set = TRUE;
+      priv->row_size = row_size;
 
-      g_object_set (scroll->priv->vadjustment,
-                    "step-increment", (gdouble) scroll->priv->row_size,
+      g_object_set (priv->vadjustment,
+                    "step-increment", (double) priv->row_size,
                     NULL);
     }
 }
@@ -1206,7 +1326,7 @@ st_scroll_view_set_mouse_scrolling (StScrollView *scroll,
 
   g_return_if_fail (ST_IS_SCROLL_VIEW (scroll));
 
-  priv = ST_SCROLL_VIEW (scroll)->priv;
+  priv = st_scroll_view_get_instance_private (scroll);
 
   if (priv->mouse_scroll != enabled)
     {
@@ -1235,7 +1355,7 @@ st_scroll_view_get_mouse_scrolling (StScrollView *scroll)
 
   g_return_val_if_fail (ST_IS_SCROLL_VIEW (scroll), FALSE);
 
-  priv = ST_SCROLL_VIEW (scroll)->priv;
+  priv = st_scroll_view_get_instance_private (scroll);
 
   return priv->mouse_scroll;
 }
@@ -1255,7 +1375,7 @@ st_scroll_view_set_overlay_scrollbars (StScrollView *scroll,
 
   g_return_if_fail (ST_IS_SCROLL_VIEW (scroll));
 
-  priv = ST_SCROLL_VIEW (scroll)->priv;
+  priv = st_scroll_view_get_instance_private (scroll);
 
   if (priv->overlay_scrollbars != enabled)
     {
@@ -1281,7 +1401,7 @@ st_scroll_view_get_overlay_scrollbars (StScrollView *scroll)
 
   g_return_val_if_fail (ST_IS_SCROLL_VIEW (scroll), FALSE);
 
-  priv = ST_SCROLL_VIEW (scroll)->priv;
+  priv = st_scroll_view_get_instance_private (scroll);
 
   return priv->overlay_scrollbars;
 }
@@ -1303,7 +1423,7 @@ st_scroll_view_set_policy (StScrollView   *scroll,
 
   g_return_if_fail (ST_IS_SCROLL_VIEW (scroll));
 
-  priv = ST_SCROLL_VIEW (scroll)->priv;
+  priv = st_scroll_view_get_instance_private (scroll);
 
   if (priv->hscrollbar_policy == hscroll && priv->vscrollbar_policy == vscroll)
     return;
index e2acaca2f599c9b3a9eafe067c8e2897e9e7d193..4a59d28ea10e2485e6848c61b0aaf064b7325f27 100644 (file)
 #error "Only <st/st.h> can be included directly.h"
 #endif
 
-#ifndef __ST_SCROLL_VIEW_H__
-#define __ST_SCROLL_VIEW_H__
+#pragma once
 
-#include <st/st-bin.h>
+#include <st/st-widget.h>
+#include <st/st-scrollable.h>
 
 G_BEGIN_DECLS
 
 #define ST_TYPE_SCROLL_VIEW            (st_scroll_view_get_type())
-G_DECLARE_FINAL_TYPE (StScrollView, st_scroll_view, ST, SCROLL_VIEW, StBin)
+G_DECLARE_DERIVABLE_TYPE (StScrollView, st_scroll_view, ST, SCROLL_VIEW, StWidget)
+
+struct _StScrollViewClass
+{
+  StWidgetClass parent_class;
+};
 
 typedef enum
 {
@@ -42,24 +47,12 @@ typedef enum
   ST_POLICY_EXTERNAL,
 } StPolicyType;
 
-typedef struct _StScrollViewPrivate   StScrollViewPrivate;
-
-/**
- * StScrollView:
- *
- * The contents of this structure are private and should only be accessed
- * through the public API.
- */
-struct _StScrollView
-{
-  /*< private >*/
-  StBin parent_instance;
-
-  StScrollViewPrivate *priv;
-};
-
 StWidget *st_scroll_view_new (void);
 
+StScrollable *st_scroll_view_get_child           (StScrollView *scroll);
+void          st_scroll_view_set_child           (StScrollView *scroll,
+                                                  StScrollable *child);
+
 ClutterActor *st_scroll_view_get_hscroll_bar     (StScrollView *scroll);
 ClutterActor *st_scroll_view_get_vscroll_bar     (StScrollView *scroll);
 
@@ -86,5 +79,3 @@ void          st_scroll_view_update_fade_effect  (StScrollView  *scroll,
                                                   ClutterMargin *fade_margins);
 
 G_END_DECLS
-
-#endif /* __ST_SCROLL_VIEW_H__ */